﻿using DSize = System.Drawing.Size;
using DPoint = System.Drawing.Point;
using DPen = System.Drawing.Pen;
using DColor = System.Drawing.Color;
using FScreen = System.Windows.Forms.Screen;
using FCursor = System.Windows.Forms.Cursor;
using System.Windows;
using System.Windows.Input;
using RPAVIEW.util;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using System.Threading;
using System;
using SUNRPA.CONTROLS.IMPL.util;
using System.Threading.Tasks;
using System.Windows.Automation;
using System.Drawing;
using System.Text;
using System.Collections.Generic;
using SRect = SUNRPA.CONTROLS.IMPL.domain.Rect;
using WRect = System.Windows.Rect;
using System.IO;
using Newtonsoft.Json.Linq;
using SUNRPA.CONTROLS.IMPL.domain;
using RPAVIEW.views.EditPage.flows;

namespace RPAVIEW.views.OtherPages {
    /// <summary>
    /// GetEleWindow.xaml 的交互逻辑
    /// </summary>
    public partial class GetEleWindow:Window {
        private static LogUtil logger = new LogUtil(typeof(GetEleWindow));
        private WRect preRect = new WRect();
        private AutomationElement currentAe;
        private Action<Element> callBack;
        private CancellationTokenSource cancelToken = new CancellationTokenSource();
        public GetEleWindow(Action<Element> afterCatchCallBack) {
            //现在这个捕捉有些更细小的控件无法捕捉到还需要继续更改(利用cv来寻找边界。截图。)
            InitializeComponent();
            //此回调函数定义了外界调用元素捕捉，再捕捉到元素后的处理方式
            callBack = afterCatchCallBack;
            IntPtr deskPtr = User32Utils.GetDesktopWindow();
            Task scanTask =  Task.Factory.StartNew(() => {
                IntPtr dc = User32Utils.GetDC(deskPtr);
                using (Graphics g = Graphics.FromHdc(dc)){
                    using(DPen pen = new DPen(DColor.Red, 5)){
                        while(!cancelToken.Token.IsCancellationRequested) { 
                            DPoint currentPoint = FCursor.Position;
                            AutomationElement ae = null;
                            try {
                                ae = AutomationElement.FromPoint(new System.Windows.Point(currentPoint.X, currentPoint.Y));
                            } catch(ElementNotAvailableException ex){ 
                                continue;
                            }
                            WRect rect = ae.Current.BoundingRectangle;
                            if(ae.Current.IsOffscreen) {
                                Thread.Sleep(10);
                                continue;
                            }
                            if(!rect.Equals(preRect)) {
                                Refresh();
                                currentAe = ae;
                                preRect = rect;
                            } else { 
                                //Thread.Sleep(50);
                                g.DrawRectangle(pen, (int)rect.TopLeft.X, (int)rect.TopLeft.Y, (int)rect.Right - (int)rect.Left, (int)rect.Bottom - (int)rect.Top);
                            }
                        }
                    }
                }
                GDIUtils.DeleteDC(dc);
            }, cancelToken.Token);
        }

        private void ChangePos(object sender, MouseEventArgs e) {
            DSize screenSize = FScreen.AllScreens[0].Bounds.Size;
            if(this.Top == 0 || this.Left == 0) {
                this.Top = screenSize.Height - this.Height;
                this.Left = screenSize.Width - this.Width;
            } else { 
                this.Top = 0;
                this.Left = 0;
            }
        }

        private void CloseWindow() {
            Refresh();
            cancelToken.Cancel();
            WindowUtil.UnRegist(ElementUtil.getWindowPtr(this));
            MainWindow main = WindowUtil.GetWindow<MainWindow>();
            WindowUtil.RecoverWindow(main);
            this.Close();
        }
        private void HideWindow() { 
            this.Hide();
        }

        public void RegistHotKey() {
            //注册快捷键
            WindowUtil.Regist(this, HotkeyModifiers.MOD_CONTROL, KeyInterop.VirtualKeyFromKey(Key.T), new WindowUtil.HotKeyCallBackHanlder(CloseWindow));
            WindowUtil.Regist(this, HotkeyModifiers.MOD_ALT, KeyInterop.VirtualKeyFromKey(Key.H), new WindowUtil.HotKeyCallBackHanlder(HideWindow));
            WindowUtil.Regist(this, HotkeyModifiers.MOD_ALT, KeyInterop.VirtualKeyFromKey(Key.C), new WindowUtil.HotKeyCallBackHanlder(CatchEle));
            WindowUtil.Regist(this, HotkeyModifiers.MOD_ALT, KeyInterop.VirtualKeyFromKey(Key.P), new WindowUtil.HotKeyCallBackHanlder(CatchEleAndPos));
        }

        //重绘桌面，去掉边框
        public void Refresh(){
            User32Utils.InvalidateRect(IntPtr.Zero, IntPtr.Zero, 1 /* TRUE */);
            User32Utils.UpdateWindow(IntPtr.Zero);
            User32Utils.RedrawWindow(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (int)ReDrawTypes.RDW_FRAME | (int)ReDrawTypes.RDW_INVALIDATE | (int)ReDrawTypes.RDW_UPDATENOW | (int)ReDrawTypes.RDW_ALLCHILDREN);
        }

        public void CatchEle() {
            FlowEditWindow win = WindowUtil.GetWindow<FlowEditWindow>();
            try {
                if(currentAe == null) { 
                    //提示处理不需要抛异常
                    MessageBox.Show("未捕捉到元素");
                    return;
                }
                cancelToken.Cancel();
                Refresh();
                //捕捉元素的时候需要知道是否为网页元素还是win元素
                //判断方法1、前景窗口为浏览器||2、指针当前窗口为浏览器 && 3、所捕捉元素不是wpf或者winform
                //由于当前支持持google浏览器，所以暂时值做google的判断其他的浏览器不做信息通信直接按照正常win元素进行处理。
                IntPtr pointW = User32Utils.WindowFromPoint(FCursor.Position);
                StringBuilder pointWindow = new StringBuilder();
                User32Utils.GetClassName(pointW, pointWindow, 2048);
                if(!BrowserType.NAB.Equals(BrowserUtil.JudgeBrowserByWindowClass(pointWindow.ToString()))
                    && !currentAe.Current.FrameworkId.Equals("WPF") 
                    && !currentAe.Current.FrameworkId.Equals("Win32")) {
                    //浏览器，需要与插件桥程序通信发送获取元素信息功能
                    using(NamedPipeClientUtil client = new NamedPipeClientUtil("localhost"
                            , DefaultContents.NAMED_PIPE_SERVER, System.IO.Pipes.PipeDirection.InOut)) {
                        
                        //获取dom页面的起始坐标(暂时通过客户端获取，今后考虑改成浏览器插件js端直接获取)
                        SRect rect = new SRect();
                        User32Utils.GetWindowRect(pointW, ref rect);
                        //获取系统放大倍数
                        double zoomSize = SystemUtil.GetSysyemZoomSize();

                        //计算出元素的像素位置
                        int eleX = (int)((preRect.X + preRect.Width / 2 - rect.Left) / zoomSize);
                        int eleY = (int)((preRect.Y + preRect.Height / 2 - rect.Top) / zoomSize);

                        NamePipeRequest req = new NamePipeRequest();
                        req.method = DefaultContents.CATCH_ELE;
                        req.requestData = new Dictionary<string, object>() { { "x", eleX }, { "y", eleY } };
                        BridgeResponse resp = client.SendRequest(req);
                        if(resp.code.Equals(CommunicationCode.OK)) {
                            //获取元素信息
                            JObject eleResult = (JObject)resp.result;
                            WebElement ele = eleResult.ToObject<WebElement>();
                            ele.EleType = ElementType.WEB;
                            string timestemp = DateUtil.GetTimeStemp();
                            string eleDirPath = ParamUtil.GetAppGlobleVar<Dictionary<string, string>>(DefaultContents.USER_DIRS)["eleLibrary"] + Path.DirectorySeparatorChar;
                            Bitmap shortCut = ImageUtil.TakeAreaCapture(preRect);
                            //get shortcut name
                            string shortCutPath = eleDirPath + timestemp + ".jpg";
                            //get elefile name
                            string eleFilePath = eleDirPath + timestemp + ".ele";
                            shortCut.Save(shortCutPath);
                            shortCut.Dispose();
                            ele.ShortCut = shortCutPath;
                            string eleString = DataUtil.ObjectJsonSerializer(ele);
                            File.WriteAllText(eleFilePath, eleString);
                            callBack(ele);
                            this.CloseWindow();
                        } else {
                            this.CloseWindow();
                            logger.Error($"捕捉网页元素出现错误：{resp.msg}", null);
                            MessageBox.Show(win, $"捕捉元素出现错误：{resp.msg}");
                            return;
                        }
                    }
                } else {
                    //不是浏览器元素则直接保存
                    this.CloseWindow();
                }
            }catch (Exception ex) { 
                this.CloseWindow();
                logger.Error($"捕捉元素出现错误：{ex.Message}", ex);
                MessageBox.Show(win, $"捕捉元素出现错误：{ex.Message}");
            }
        }

        public void CatchEleAndPos() {

        }

        private void WindowClosed(object sender, EventArgs e) {
            CloseWindow();
        }
    }
}
